Sesión 1: Introducción a R y RStudio
Taller de Estadística aplicada en R para ciencias sociales - POLITAI
¿Qué buscamos con el taller?
Familiarizarnos con el lenguaje, el uso de R y explorar los formas más comunes y útiles para el análisis de datos.
No es un curso exhaustivo que cubra todas las aplicaciones y posibilidades que se pueden aprovechar con R.
Ejemplos de informes…
Repasemos la instalación de…
Otra opción es RStudio Cloud
Esta plataforma se define como un Cloud computing. Es decir, el hardware, software, datos y recursos que utilizas para tus cursos de estadística pasan de estar en nuestras computadoras a “la nube”.
Configurar el directorio de trabajo
Es fundamental considerar la ubicación de los archivos al importar y exportar nuestros datos. Esta carpeta, en la que se cargan los archivos, se conoce como “Working directory” o directorio de trabajo.
Para encontrar nuestro lugar actual de trabajo o el “Set Working Directory”, debemos correr el siguiente comando en la consola:
getwd()(sin las comillas invertidas). Si ejecuta este comando desde un archivo Rmd, obtendrá la ubicación del archivo script actual.Para cambiar nuestro directorio de trabajo a uno específico, podemos utilizar la siguiente función:
setwd() # Establecer el nuevo directorio
dir() # Ver qué archivos están en el directorio o en el lugar en que se encuentreOtra opción para establecer nuestro directorio de trabajo:
- Nos dirigirnos al menú superior y seleccionamos las siguientes pestañas: “Session” > “Set Working Directory” > “Choose Directory”. Esto abrirá una ventana emergente, en la que podemos buscar la carpeta en la cual deseamos trabajar. Una vez ubicada, la seleccionamos y hacemos clic en “Open”. Para verificar el cambio, volvemos a ejecutar la función
getwd()en la consola.
- Nos dirigirnos al menú superior y seleccionamos las siguientes pestañas: “Session” > “Set Working Directory” > “Choose Directory”. Esto abrirá una ventana emergente, en la que podemos buscar la carpeta en la cual deseamos trabajar. Una vez ubicada, la seleccionamos y hacemos clic en “Open”. Para verificar el cambio, volvemos a ejecutar la función
Si necesitamos importar, por ejemplo, una base de datos desde otra subcarpeta (dfs, en este caso):
library(rio)
data = import("./dfs/pavimentandoconvotos.sav")
# './' El punto + el slash indican que importaremos
# la base de una subcarpeta llamada 'dfs'- Luego aprenderán otros modos para importar bases de datos directamente desde internet.
¿Qué es R?
R es un lenguaje y software que permite análisis estadísticos y gráficos.
Lenguaje porque posee su propia sintaxis, a partir de la cual se pueden escribir sentencias y comandos.
Es un software porque es al mismo tiempo un programa con múltiples funcionalidades
… ¿Y RStudio?
Rstudio es un integrated development environment - IDE: un interfaz amigable y poderoso para trabajar con R.
Pero si hay más softwares estadísticos, ¿por qué usamos (o deberíamos usar) R?
Costo: Software libre
Potencia (N° herramientas): Comunidad que crea nuevas herramientas (packages) constantemente.
Accesibilidad al usuario: Lenguaje de Programación R (Antes de 1970)
¿Pará qué podemos usar R?
Proporciona una amplia variedad de herramientas para generar visualizaciones y personalización de gráficos de datos de alta calidad, además, junto con Rstudio permiten la automotización de reportes y la replicabilidad de los análisis mediante el uso de scripts.
Pero también…
Es una herramienta de procesamiento estadístico: limpieza, manejo, almacenamiento de datos e integración con distintas bases de datos o lenguajes de otros programas (Spss, Python o Stata)
Amplia variedad de técnicas estadísticas para el análisis de datos: modelos lineales, pruebas estadísticas, análisis de series de tiempo, clasificación, agrupación, enter otros.
Posibilidad de creación de librerías propias para trabajos en específico
Implementar análisis con algoritmos de Machine Learning, data mining y big data.
Web Scraping, generar tableros o aplicaciones como shiny
Después de lo que se ha expuesto, les animo a que continúen explorando R y sus diversos usos a través de diferentes fuentes, siendo este curso una de ellas.
INTERFAZ
- 4 paneles (en esentido horario):
1. Console (La consola)
Útil cuando queremos ejecutar porciones de código pequeñas.
Realizar cálculos y operaciones matemáticas como una calculadora avanzada.
Visualizar y registrar el output de nuestros códigos
cars speed dist
1 4 2
2 4 10
3 7 4
4 7 22
5 8 16
6 9 10
7 10 18
8 10 26
9 10 34
10 11 17
11 11 28
12 12 14
13 12 20
14 12 24
15 12 28
16 13 26
17 13 34
18 13 34
19 13 46
20 14 26
21 14 36
22 14 60
23 14 80
24 15 20
25 15 26
26 15 54
27 16 32
28 16 40
29 17 32
30 17 40
31 17 50
32 18 42
33 18 56
34 18 76
35 18 84
36 19 36
37 19 46
38 19 68
39 20 32
40 20 48
41 20 52
42 20 56
43 20 64
44 22 66
45 23 54
46 24 70
47 24 92
48 24 93
49 24 120
50 25 85
head(cars) speed dist
1 4 2
2 4 10
3 7 4
4 7 22
5 8 16
6 9 10
names(cars)[1] "speed" "dist"
str(cars)'data.frame': 50 obs. of 2 variables:
$ speed: num 4 4 7 7 8 9 10 10 10 11 ...
$ dist : num 2 10 4 22 16 10 18 26 34 17 ...
mean(c(1,2,3,4,5))[1] 3
2. Script (El editor)
Panel en el que se crean y modifican scripts, entre otros tipos de archivos…
Por ejemplo, para crear un script de extensión .R: vamos a File > New File > R Script.
Para abrir un script guardado en la computadora, vamos a File > Open File
2.1. knitting en RStudio
Vamos a trabajar en archivos con extension Rmarkdown (Rmd) y otros, pero para presentarlos de una manera amigable, podemos exportarlos en formato PDF, Html o en una página web.
Para Html, seleccionamos en el menú Knit > Knit to html
Para pdf, seleccionamos Knit > Knit to PDF, pero antes de exportar en pdf deberá instalar lo siguiente desde su consola:
install.packages(‘tinytex’)
tinytex::install_tinytex()
Asimismo, para un Knit a una página web, utilizaremos Rpubs, por lo que deberán crearse una cuenta.
- Recomendación: Cuando creen sus archivos Rmd, que estos no contengan en su nombre caracteres como tildes, símbolos, etc., eso no les permitirá realizar un knit en la web.
Diferencias sobre este tipo de archivos: Script, R Markdown y R Notebook
Puedes revisar este Rpubs de Gustavo Martínez Valdes para mejorar tu YAML:
- YAML (Yet Another Markdown Language): Allí se configuran las características generales que se arrojarán en el documento de salida o output, una vez que el documento en formato Markdown haya sido renderizado (con el comando
knitr()).
- YAML (Yet Another Markdown Language): Allí se configuran las características generales que se arrojarán en el documento de salida o output, una vez que el documento en formato Markdown haya sido renderizado (con el comando
2.2. Github
Vamos a requerir que se creen una cuenta en GitHub. Esta plataforma permite alojar proyectos utilizando el sistema de control de versiones Git. Se utiliza principalmente para la creación de código fuente de programas de ordenador. Para fines de este curso, vamos a utilizar Github como repositorio para cargar nuestras bases de datos, administrar nuestros archivos etc.
Pueden crearse una cuenta en el siguiente enlace de Github: Log in or Sign Up.
Github como repositorio:
En la parte superior derecha seleccione “+”, seleccione “New repository” y siga los pasos precisando el nombre del respositorio, descripción (opcional), elija la visibilidad del repositorio (publico o privado) y cree su repositorio.
Cargue archivos seleccionando Add file > Upload files > Choose your files > Commit changes
3. Environment (El entorno de variables)
Advertimos los objetos creados, pero tambien dataframes, tibbles, listas, entre otros.
¿Qué es una variable?
- Una variable es un espacio en la computadora en el que guardamos un objeto (como una caja con un nombre determinado para guardar cosas).
media <- mean(c(1,2,3,4,5,6))dataair <- airquality4. Panel de Visualización
Se encuentran los archivos del usuario como si fuera la carpeta de “Mis Documentos” en Windows. De esta manera podemos acceder fácilmente a archivos de nuestra computadora y de nuestro directorio de trabajo.
boxplot(airquality)#install.packages("tinytex")5. Menú superior
- File
- View: Zoom in, Zoom out
- Session
- Tools
- Entre otros
Configuremos RStudio!
Solo algunos cambios para iniciar…
- Nos dirigimos al menú superior: “Tools” > “Global options…” > “Code”…
> “Display” > y marcamos lo siguiente:
“Show line numbers”
“Highlight R funtion Calls”
“Rainbow parentheses”
> “Saving” y cambiamos en “Default text encoding:” a “UTF-8”
- Luego nos dirigimos: “Tools” > “Global options…”
> “Appereance” > y marcamos lo siguiente:
RStudio theme: Modern
Zoom: 175%
Editor font: Lucida Font
Editor font size: 10
Editor theme: Pastel On Dark
Ojo: podemos realizar estos cambios y otros según nuestra curiosidad o interés.
Pero también es importante mejorar nuestros reportes…
Tomemos en cuenta la siguiente sintaxis de Rmd:
bolding words <- negrita
italicizing words <- cursiva
striking through<- tachando- Puedes combinar las anteriores: Cuantipol
‘comillas simples’ <- alt + 3 + 9 <- ’’
comillas invertidas<- alt + 9 + 6 <- ``Para escribir una nueva oración, debemos dejar una linea de código para que no se junte todo en un solo párrafo.
# Título
## Subtítulo
###Realizar comentarios de los comandos en el code chunk o en el script con la almohadilla o el numeral: #
- Por ejemplo: Importemos los nombres del dataset starwars:
library(tidyverse) # Necesario para llamar al dataset
# Sin este numeral, no se podría comentar
# ni ejecutar los códigos en este code chunk
names(starwars) # Nombres de la data [1] "name" "height" "mass" "hair_color" "skin_color"
[6] "eye_color" "birth_year" "sex" "gender" "homeworld"
[11] "species" "films" "vehicles" "starships"
En ese sentido, para programar de manera ordenada, es de utilidad comentar el código utilizado y proporcionar una explicación precisa de lo que se realiza con cada función. Esto no solo nos ayuda a nosotros mismos a entender claramente el propósito de cada función cuando volvamos a revisar nuestro código, sino que también resulta útil para nuestros colegas que revisarán nuestra investigación.
Es necesario comentar que los primeros lenguajes de programación tienen una fuerte influencia anglosajona. En 1963, se creó el código ASCII, un conjunto de caracteres basado en el alfabeto latino utilizado en el inglés moderno (Mackenzie, 1980). En consecuencia, las primeras computadoras IBM adoptaron el estándar ASCII. Esto puede provocar dificultades en la lectura de caracteres especiales como “ñ”, “ó” o “ü”. Por tanto, al manipular datos, debemos considerar lo siguiente:
Guardar los objetos con nombres cortos, autodescriptivos, sin espacios y sin caracteres especiales. Del mismo modo con las variables dentro de los objetos.
Al exportar los datos, verificar si los nombres de los objetos y las variables dentro de ellos se han exportado correctamente, sin problemas de codificación (“encoding”). Por ejemplo, al exportar a formato
.dta, los nombres de las variables podrían aparecer de la siguiente manera:variable variable en .dtaCorrecto nombre de variable año a?o year educación educaci?n edu antigüedad antig?edad antiguedad
Consideremos otros consejos respecto a los code chunk:
Nota: para advertir los cambios, es necesario comparar el script y el informe.
# Code chunk básicoCódigo para no mostrar las advertencias y mensajes para todo nuestro reporte:
Lo anterior, pero solo para un code chunk:
- Ojo: include = FALSE <- No muestra el código ni su resultado ni texto, etc., en el reporte.
Si solo queremos visualizar el resultado, pero no el código:
Para mostrar el código, los gráficos, etc., y el resultado de su función:
- eval=TRUE
# Compruebalo al Knitear este informe:
#library(scatterplot3d)
#(f <- scatterplot3d(airquality[,c('Ozone', 'Wind', 'Month')]))Para mostrar el código, los gráficos, etc., pero no el resultado de su función:
- results=FALSE
# Por ejemplo:
library(scatterplot3d)
(f <- scatterplot3d(airquality[,c('Ozone', 'Wind', 'Month')]))Atajos útiles de teclado, los más importantes…
Podemos ver todos los atajos en el Panel de atajos: tools > Keyboard Shortcuts Help <- alt + shift + k
Crear code chunk <- Ctrl + Alt + i
Correr/ejecutar code <- Alt + Enter
names(starwars) [1] "name" "height" "mass" "hair_color" "skin_color"
[6] "eye_color" "birth_year" "sex" "gender" "homeworld"
[11] "species" "films" "vehicles" "starships"
Guardar avance <- Ctrl + S
Ejecutar linea de código <- Ctrl + Enter
Knitear/renderizar a pdf/hml/etc <- Ctrl + Shift + k
Dar formato ordenado al código <- Ctrl + A
Para comentar múltiples líneas de código en un chunk: agrega el numeral al lado izquierdo en cada línea de código <- Ctrl/cmd + Shift + C
Para buscar y reemplazar varias palabras <- Ctrl + F
Reiniciar Rstudio <- Ctrl + shift + f10
Insertar ‘pipe’ <- Ctrl + shift + m <-
|>o el pipe antiguo: %>%Operador de asignación <- Alt + - (guion) o también podemos usar: <-
Arrastrar línea de código <- Alt + up o Alt + down
Para desplazarnos en cada pestaña de los scripts <- Ctrl + Alt + (flechas: izquierda o derecha)
Para insertar/crear secciones (títulos) <- Ctrl/cmd + shift + R
Instalación de paquetes
Para instalar un paquete solo debes correr el siguiente comando con el nombre del paquete dentro del paréntesis entre comillas.
#install.packages("tidyverse")Cuando instalas un paquete estás descargando una serie de funciones con un solo comando.
Recuenden: Los comandos en R tienen que estar con los espacios, comas, comillas, paréntesis y puntos exactamente de cierta forma , sino el comando no correrá! Es recomendable correr este comando en la consola porque solo se tiene que descargar un paquete una vez por lo cual si dejas el comando en tu script se podría volver a correr reinstalando un paquete instalado.
En efecto, esto va a suceder otras veces con todos los paquetes que quieras instalar y abrir. Ya que puedes ya tener el paquete descargado pero si no lo abres con el comando library, no podrás utilizar sus funciones.
Otra opción es abrir solo el o los paquetes que necesitas usar ya que abrir el paquete de tidyverse a veces demora un poco debido a que son varios paquetes.
library(dplyr)
library(ggplot2)
library(tidyr)
library(purrr)
library(knitr)Pero el paquete {pacman} nos permite realizar ambas acciones al mismo tiempo de la siguiente manera:
Instalar el paquete pacman en la consola:
install.packages(“pacman”)
Luego correr en un code chunk lo siguiente:
# instalar e invocar paquetes:
pacman::p_load(dplyr, ggplot2, tidyr, purrr, knitr)
# Hicimos todo lo anterior solo en una linea de codigo.Algo más: Organización de carpetas
Es importante conservar un orden para realizar análisis de datos o una investigación. Se sugiere la siguiente estructura:
Nombre de la carpeta principal
códigos
datos
- original
- procesados
resultados
- tablas
- gráficos
- Htmls, Pdfs, etc
literatura
Les exhorto revisar los foros de la comunidad de programadores como StackOverflow en la que se realizan y absuelven dudas frecuentes o específicas.
Elementos fundamentales
Sintaxis en R
Hasta ahora, parece que toda la acción es consecuencia de haber corrido un código. En fecto, casi todo está compuesto por códigos y la combinación de estos forma una sintaxis. Además, R almacena la información de nuestras observaciones y variables en objetos. En ese sentido, la estructura general de una sintaxis puede resumirse de la siguiente manera:
A un objeto determinado se le asigna el resultado de una función, que a su vez se ejecuta sobre un conjunto de datos especificado, con una serie de configuraciones particulares.
- Por ejemplo:
Entonces, la línea de comando puede explicarse así (de izquierda a derecha):
Primero se indica un objeto a crear, con el nombre que ustedes definan.
Luego se indica el asignador, que expresa que todo lo que esté a la derecha de la flecha se guardará en el objeto creado a la izquierda. El asignador puede ser “<-” o también “=”
A continuación, encontramos la función que, en este caso, nos permite leer archivos de tipo Microsoft Excel. Notemos que R utiliza funciones que están disponibles en “paquetes” desarrollados por la comunidad. Podemos realizar nuestras operaciones utilizando diferentes funciones, ya que no existe una única forma de hacerlo. Si deseamos utilizar funciones que no están incluidas por defecto en R, debemos instalar el paquete y cargar la libreria respectivos para ejecutarlas.
Luego de la función, se abre un paréntesis que contiene los argumentos: instrucciones que especifican ciertos detalles de lo que queramos que la función realice. Los argumentos pueden escribirse de distintas maneras y va a depender de lo que queramos hacer. En nuestro ejemplo:
El primer argumento indica la información a leer, en este caso indica un archivo de tipo Excel (extensión xlsx).
El segundo argumento indica la hoja del archivo a leer.
El tercer argumento indica qué columnas se leerán de forma específica (en este caso, las primeras diez).
Valores
Es el elemento más básico que existe en el entorno de R
- Son valores numéricos:
3[1] 3
9*5 [1] 45
7+6[1] 13
- Son valores character:
"mes"
"un mes"- FALSE es un valor booleano o lógico
7+6 > 45[1] FALSE
Vectores
Recordemos los vectores en matematicas o física:
Algo que tenia magnitud o modulo, direccion y sentido, y que los componentes de un vector se guardan en coordenadas:
- Una cosa como (x,y,z)
Un vector es un espacio de memoria en la computadora que se usa para guardar informacion de cualquier cosa. Efectivamente, los vectores son una colección de valores.
Para agrupar esos valores utilizamos el comando c()
- Así es,
cya es una función en R, y si crea una variable con el mismo nombre, significaría que ya no se podría usarc()para combinar/concatenar elementos.
Estos vectores también pueden ser de distinto tipo:
c(9, 9*5)[1] 9 45
c("mes", "un mes")[1] "mes" "un mes"
c(9*5, "mes")[1] "45" "mes"
Objetos
Notar que ninguno de los valores ni vectores anteriores fueron almacenados en un objeto. Si quisiera llamarlos, ¿cómo haría?
Debo definirlos, especificando tres inputs:
nombre del objeto
utilizar el operador asignación <- (pensarlo como un =)
contenido
a <- 7 + 6
a[1] 13
En el ejemplo anterior, se ha creado un objeto a y luego se ha llamado ese mismo objeto para que muestre lo que lleva adentro (13).
Ahora, crearé el objeto b:
5 + 1 -> b
b[1] 6
El objeto a y b son vectores numéricos por lo que puedo realizar operaciones entre ellos. En primera instancia puedo sumarlos entre ellos y/o con otros números:
h <- a+b
h[1] 19
a + b + 6[1] 25
¿Pero hay más tipos de vectores?…
Tipos de objetos en R
Una parte clave para iniciar el manejo del programa es identificar los diversos objetos que podemos crear, manipular y utilizar. Para la definición de objetos en R será necesario previamente tener claridad teórica sobre lo que es una variable categórica nominal, categórica ordinal, numérica discreta y numérica continua.
| Nombre | Ejemplo | Name |
|----------|---------|-----------|
| Entero | 1 | Integer |
| Numérico | 1.8 | Numeric |
| Caracter | "uno" | Character |
| Factor | uno | Factor |
| Logico | TRUE | Logical |
| Perdido | NA | Missing |
| Vacío | NULL | null |
Del mismo modo para los vectores:
- Definir un objeto me permite luego llamarlo para distintas operaciones (lo que se conoce como vectorización)
R se conoce como un lenguaje vectorizado y las estructuras de datos básicas en R son todas vectores. Por ejemplo, cuando creamos la variable h anteriormente, parecía que era solo un número entero e integer. Pero en realidad, R almacena esto como un vector – una lista ordenada de elementos del mismo formato (en este caso, double values).
Podemos ver el tipo de los elementos en un vector usando la función typeof, y podemos ver cuántos elementos hay en el vector usando la función length:
typeof(h) # Tipo de los elementos[1] "double"
length(h) # Cuantos elementos hay en el vector[1] 1
Vector numérico
- Vector conformado por la concatenación de números, puede representar variables numéricas continuas o discretas. Ej: 1.5, 2.7, 3.1
Como vimos anteriormente, un vector numérico se compone de uno o más números lo que nos permite realizar operaciones aritméticas. Por ejemplo:
#un número=3
g <- 1 + 2
#dos números=c(1,2)
d <- c(1, 2)
#c es un vector numérico
class(g)[1] "numeric"
Cuando tenemos un vector con más de un número, las operaciones aritméticas que realizamos se aplican a cada uno de sus elementos:
#Cada elemento de d x 2
d*2[1] 2 4
vect0 <- c(1, 3, 4)
vect0[1] 1 3 4
vect1 <- vect0 + 12
vect1 # Los vectores se suman en parelelo[1] 13 15 16
vect2 <- vect0 + (12:14)
vect2 # Los vectores se suman en parelelo[1] 13 16 18
Vector de caracteres / vector de factores
Vector que sirve para representar variables categóricas. Pudiendo ser factores nominales u ordinales.
Ej:
“costa”, “sierra”, “selva”.
Género: Masculino, femenino
Nivel de confianza en instiuciones: muy alto, alto, bajo
Por ejemplo:
cuan1 <- "genteeeeeee,"
cuan2 <- "ahora, sí se acabó el recreo"
cuanti <- paste(cuan1, cuan2)
print(cuanti)[1] "genteeeeeee, ahora, sí se acabó el recreo"
En un vector no se permite que se realicen operaciones aritméticas; no obstante, podríamos calcular la frecuencia con que se repite cada elemento. Por ejemplo:
ejemplo <- c("Y", "la", "queso", 3,
"Y", "la", "queso", 3,
"Y", "la", "queso", 3)
ejemplo [1] "Y" "la" "queso" "3" "Y" "la" "queso" "3" "Y"
[10] "la" "queso" "3"
class(ejemplo) [1] "character"
El objeto ejemplo es un vector “character” que engloba texto únicamente, por lo que podemos contabilizar cuántos elementos repetidos tiene:
table(ejemplo)ejemplo
3 la queso Y
3 3 3 3
Nótese que aunque se ha incluido un número a propósito (el 3) dentro de un vector con texto, igual reconoce este número como un texto. En este caso, se podría hacer la equivalencia: 3="3"="tres". Es por ello que cuando realizamos una tabla de frecuencias contabiliza cuántos 3 hay en vez de sumar los tres 3s.
Ya pero, ¿qué son los factores en R?
Una estructura de datos para manejar variables categoricas.
Las variables categóricas son datos que toman una cantidad finita de valores
Por ejemplo:
- Rango de edad: niño, joven, adulto
- Colores: rojo, verde, amarillo, …
- Días de la semana: L/M/M/J/V/S/D
- Entre otros…
En analisis de datos, las variables categoricas se tratan de manera diferente a las variables continuas o numericas.
Necesitamos un objeto en R para ello. Los factores permiten trabajar con modelos y graficas de variables categoricas (aquí su importancia).
Vector lógico
Un objeto lógico es un vector booleano dicotómico cuyos valores pueden ser únicamente TRUE o FALSE. Por ejemplo:
resultados <- c(TRUE, TRUE, FALSE, FALSE)
class(resultados)[1] "logical"
Los vectores lógicos son útiles cuando se trabaja con condiciones lógicas del tipo if else. Por ejemplo:
# una abreviación para TRUE es T y para FALSE es F
aprueba_examen = T
reprueba_examen = F
# if(vector lógico){en caso TRUE}else{en caso FALSE}
if(aprueba_examen) {"Felicitaciones"}else{"Más suerte a la próxima"}[1] "Felicitaciones"
if (reprueba_examen) {"Felicitaciones"}else{"Más suerte a la próxima"}[1] "Más suerte a la próxima"
Pero tambien podemos utilizar tipicos operadores matematicos para comparar valores. El simbolo del doble igual comprobara si, por ejemplo, estos dos valores son iguales. Mientra que el signo del mayor que comprobara si una variable lo es, efectivamente, sobre otra:
aprueba_examen == reprueba_examen [1] FALSE
aprueba_examen > reprueba_examen [1] TRUE
Se cuenta con diferentes operadores lógicos, como se muestra en la siguiente tabla:
| Operator | Meaning |
|---|---|
x & y |
Devuelve TRUE solo si x es TRUE and y es TRUE |
x | y |
Returns TRUE only if x is TRUE or y is TRUE (or both are!) |
!x |
Llamado not, este operador voltea todos los elementos TRUE en x a FALSE (y viceversa) |
x == y |
Returns TRUE if x is equal to y. Watch out! We use two equal signs to check if numbers are the same, not a single equal sign. |
x < y |
Returns TRUE if x is less than y. If you want to see if x is less than or equal to y you can use <=, and the reverse of these two operators, > and >=, also are available. |
Podemos emplear el comando class() de forma genérica para conocer qué tipos de datos son…
Por ejemplo:
class(8)[1] "numeric"
class("UNMSM")[1] "character"
class(TRUE) [1] "logical"
Funciones (comandos)
Las funciones son comandos, son expresiones que encierran una orden predeterminada.
Al invocar una función le estaremos diciendo a R que realice una tarea particular.
Para ejecutar una función R necesita de dos inputs:
- Nombre de la función
- Argumento
Data Frames (base de datos)
- En ese caso, basado en vectores
Es una estructura de datos en la que se utilizan diferentes tipos de variables o vectores que constituyen una matriz. Entonces, encontramos columnas con caracteres, numeros y variables logicas.
- Son importantes para graficas, analisis y modelos con muchas variables estadisticas
Por ejemplo:
df <- data.frame(
persona = c("Joel", "Santiago", "María Pía", "Pavel"),
nota = c(15, 17, 20, 16),
aprueba = c(F, T, T, T))
df persona nota aprueba
1 Joel 15 FALSE
2 Santiago 17 TRUE
3 María Pía 20 TRUE
4 Pavel 16 TRUE
En este dataframe de valores aleatorios podemos ver que tenemos los tres tipos de vectores = character, numérico, y lógico. Cabe mencionar que deben haber el mismo número de valores dentro de cada vector, es por ello que, cada vector cuenta con 4 valores.
Asimismo, un dataframe nos permite generar variables a partir de los valores de otras variables presentes en el dataframe. Por ejemplo:
df$mensaje <- ifelse(df$aprueba,
"Felicitaciones",
"Más suerte a la próxima")
df persona nota aprueba mensaje
1 Joel 15 FALSE Más suerte a la próxima
2 Santiago 17 TRUE Felicitaciones
3 María Pía 20 TRUE Felicitaciones
4 Pavel 16 TRUE Felicitaciones
Pero en este curso, comúnmente, también encontraremos y, a veces, crearemos:
lists, que parecen vectores pero tienen elementos de diferentes tipos
functions, que se denominan closures (cierres) en R y operan con datos
Entre otros
Programando en R
TYDIVERSE???
Tidyverse es un conjunto de de paquetes de R para ciencia de datos, nos ayuda a trabajar las bases de datos. Ha sido desarrollado por RStudio.
Es consistente : Todos los paquetes tienen una misma estructura
Concatenable: Siempre se pueden unir pequeñas partes para resolverlos
Funcional: Como casi todo R, promueve la programación
Para cada paso de tratamiento de datos existe un paquete, se puede pasar desde cargar/importar los datos, limpiarlos, transformarlos, visualizar, modelarlos y finalmente comunicarlos.
Para importar datos tenemos readr, haven y readxl. Para limpiar los datos usamos tidyr, para transofrmar los datos se usa dyplr, que lo veremos a continuación, para modelar se usa purr o broom, para visualizar se usa ggplot2. Finalmente, para comunicar se usa knitr para publicar los resultados por html, pdf, ppt. y rmarkdown es la estructura de knitr.
Algunos les gusta usarlo porque facilita el análisis y manipulación de datos y es más rápido, pero, por otro lado, tiene otra lógica en la programación. En vez de usar “,” para diferenciar entre comandos, usar %>%,
Instalando el paquete de tidyverse te incluye los 8 paquetes. Pero, eso sí, toma más tiempo de lo debido. Por eso, en esta ocasión, se ha descargado los que necesitaremos ahora
# Paquetes que se usarán
library(dplyr)
library(ggplot2)
library(data.table)
library(devtools)
library(foreign)
library(rio)Sobre la data a analizar
Importar y preparar base de datos
Un método más rápido y versatil:
#getwd()
#setwd("")
#dir()
library(rio)
df_usa = import("usa.sav")
names(df_usa) [1] "id" "region" "consipol" "edad" "intecamp" "clintpre"
[7] "gorepre" "gbushpre" "aborto" "anonac" "educ" "sexo"
[13] "ingresos" "marital" "voto96" "quien96" "su_ecopas" "clintpst"
[19] "gorepst" "gbushpst" "relig" "voto00" "confipol" "difclint"
str(df_usa)'data.frame': 1807 obs. of 24 variables:
$ id : num 1347 1226 1300 1646 799 ...
..- attr(*, "label")= chr "Identificacion"
..- attr(*, "format.spss")= chr "F4.0"
$ region : num 3 3 2 2 3 4 3 2 3 2 ...
..- attr(*, "label")= chr "Region del entrevistado"
..- attr(*, "format.spss")= chr "F1.0"
..- attr(*, "labels")= Named num [1:4] 1 2 3 4
.. ..- attr(*, "names")= chr [1:4] "1. Noreste" "2. Norte Centro" "3. Sur" "4. Oeste"
$ consipol : num NA 4 2 5 5 NA 5 6 6 5 ...
..- attr(*, "label")= chr "Politicamente se considera?"
..- attr(*, "format.spss")= chr "F1.0"
..- attr(*, "labels")= Named num [1:7] 1 2 3 4 5 6 7
.. ..- attr(*, "names")= chr [1:7] "1. Muy liberal" "2. Liberal" "3. Algo liberal" "4. Moderado" ...
$ edad : num 97 96 95 93 93 92 91 90 90 89 ...
..- attr(*, "label")= chr "Edad"
..- attr(*, "format.spss")= chr "F2.0"
$ intecamp : num 5 3 5 3 1 5 3 1 1 5 ...
..- attr(*, "label")= chr "Le interesan las campañas?"
..- attr(*, "format.spss")= chr "F1.0"
..- attr(*, "labels")= Named num [1:3] 1 3 5
.. ..- attr(*, "names")= chr [1:3] "1. Mucho" "3. Poco" "5. Nada"
$ clintpre : num 40 85 100 NA 85 50 30 50 60 NA ...
..- attr(*, "label")= chr "Aceptacion de Clinton Pre Eleccion"
..- attr(*, "format.spss")= chr "F3.0"
..- attr(*, "labels")= Named num [1:2] 997 998
.. ..- attr(*, "names")= chr [1:2] "997. DON'T RECOGNIZE" "998. DK WHERE TO RATE"
$ gorepre : num 60 85 85 NA 60 50 40 60 70 NA ...
..- attr(*, "label")= chr "Aceptacion de Al Gotre Pre Eleccion"
..- attr(*, "format.spss")= chr "F3.0"
..- attr(*, "labels")= Named num [1:2] 997 998
.. ..- attr(*, "names")= chr [1:2] "997. DON'T RECOGNIZE" "998. DK WHERE TO RATE"
$ gbushpre : num 80 70 70 NA 90 50 70 60 80 NA ...
..- attr(*, "label")= chr "Aceptacion de Bush Pre Eleccion"
..- attr(*, "format.spss")= chr "F3.0"
..- attr(*, "labels")= Named num [1:2] 997 998
.. ..- attr(*, "names")= chr [1:2] "997. DON'T RECOGNIZE" "998. DK WHERE TO RATE"
$ aborto : num 1 2 2 4 4 2 2 1 2 1 ...
..- attr(*, "label")= chr "Que opina del aborto?"
..- attr(*, "format.spss")= chr "F1.0"
..- attr(*, "labels")= Named num [1:4] 1 2 3 4
.. ..- attr(*, "names")= chr [1:4] "1. Nunca permitir" "2. Solo caso de violacion" "3. Solo en Caso de Salud" "4. Permitir"
$ anonac : num 1 1 1 NA 1 1 1 1 1 1 ...
..- attr(*, "label")= chr "Año que nació?"
..- attr(*, "format.spss")= chr "F1.0"
..- attr(*, "labels")= Named num [1:3] 1 2 3
.. ..- attr(*, "names")= chr [1:3] "1949 o antes" "1950-1965" "Despues de 1965"
$ educ : num 1 1 1 3 1 1 2 3 3 1 ...
..- attr(*, "label")= chr "Nivel Educativo"
..- attr(*, "format.spss")= chr "F3.0"
..- attr(*, "labels")= Named num [1:3] 1 2 3
.. ..- attr(*, "names")= chr [1:3] "1. Menos que Secundaria" "2. Secundaria Completa" "3. Más que secundaria"
$ sexo : num 2 2 2 2 1 1 2 2 2 2 ...
..- attr(*, "label")= chr "Sexo"
..- attr(*, "format.spss")= chr "F1.0"
..- attr(*, "labels")= Named num [1:2] 1 2
.. ..- attr(*, "names")= chr [1:2] "Hombre" "Mujer"
$ ingresos : num NA 36297 3856 NA 83308 ...
..- attr(*, "label")= chr "Ingresos"
..- attr(*, "format.spss")= chr "F3.0"
$ marital : num 1 2 2 2 2 1 2 2 2 2 ...
..- attr(*, "label")= chr "Estado Civil"
..- attr(*, "format.spss")= chr "F1.0"
..- attr(*, "labels")= Named num [1:6] 1 2 3 4 5 6
.. ..- attr(*, "names")= chr [1:6] "1. Casado" "2. Viudo" "3. Divorciado" "4. Separado" ...
$ voto96 : num 5 NA 1 1 1 1 1 1 1 5 ...
..- attr(*, "label")= chr "Voto en las elecciones anteriores?"
..- attr(*, "format.spss")= chr "F1.0"
..- attr(*, "labels")= Named num [1:2] 1 5
.. ..- attr(*, "names")= chr [1:2] " Votó" "No votó"
$ quien96 : num NA NA 1 3 5 3 3 1 3 NA ...
..- attr(*, "label")= chr "Por quien voto esa vez?"
..- attr(*, "format.spss")= chr "F1.0"
..- attr(*, "labels")= Named num [1:4] 1 3 5 7
.. ..- attr(*, "names")= chr [1:4] "1. Bill Clinton" "3. Bob Dole" "5. Ross Perot" "7. Other"
$ su_ecopas: num NA NA 1 2 2 1 2 NA NA 3 ...
..- attr(*, "label")= chr "Su situacion economica el año pasado?"
..- attr(*, "format.spss")= chr "F1.0"
..- attr(*, "labels")= Named num [1:3] 1 2 3
.. ..- attr(*, "names")= chr [1:3] "1. Mejor" "2. Igual" "3. Peor"
$ clintpst : num NA 50 NA NA 30 20 NA 80 80 NA ...
..- attr(*, "label")= chr "Aceptacion de Clinton Post Eleccion"
..- attr(*, "format.spss")= chr "F3.0"
..- attr(*, "labels")= Named num [1:2] 997 998
.. ..- attr(*, "names")= chr [1:2] "997. NS" "998. no puede rankear"
$ gorepst : num NA 50 NA NA 40 50 NA 50 75 40 ...
..- attr(*, "label")= chr "Aceptación de Al Gore Post Eleccion"
..- attr(*, "format.spss")= chr "F3.0"
..- attr(*, "labels")= Named num [1:2] 997 998
.. ..- attr(*, "names")= chr [1:2] "997. NS" "998. no puede rankear"
$ gbushpst : num NA 50 NA NA 100 65 NA NA 90 NA ...
..- attr(*, "label")= chr "Aceptación de Bush Post Eleccion"
..- attr(*, "format.spss")= chr "F3.0"
..- attr(*, "labels")= Named num [1:2] 997 998
.. ..- attr(*, "names")= chr [1:2] "997. NS" "998. no puede rankear"
$ relig : num 7 1 1 1 1 1 1 1 1 2 ...
..- attr(*, "label")= chr "Religion"
..- attr(*, "format.spss")= chr "F3.0"
..- attr(*, "labels")= Named num [1:4] 1 2 3 7
.. ..- attr(*, "names")= chr [1:4] "Protestante" "Catolico" "Judio" "Otro"
$ voto00 : num NA 5 NA 1 1 1 NA 1 5 5 ...
..- attr(*, "label")= chr "Voto en estas elecciones?"
..- attr(*, "format.spss")= chr "F3.0"
..- attr(*, "labels")= Named num [1:2] 1 5
.. ..- attr(*, "names")= chr [1:2] "Votó" "NO votó"
$ confipol : num NA NA NA NA 1 2 NA 2 4 2 ...
..- attr(*, "label")= chr "Confianza en la politica"
..- attr(*, "format.spss")= chr "F1.0"
..- attr(*, "labels")= Named num [1:4] 1 2 3 4
.. ..- attr(*, "names")= chr [1:4] "1. Baja" "2. Media Baja" "3. Media Alta" "4. Alta"
$ difclint : num NA -35 NA NA -55 -30 NA 30 20 NA ...
..- attr(*, "format.spss")= chr "F8.2"
..- attr(*, "display_width")= int 10
class(df_usa) [1] "data.frame"
head(df_usa) id region consipol edad intecamp clintpre gorepre gbushpre aborto anonac
1 1347 3 NA 97 5 40 60 80 1 1
2 1226 3 4 96 3 85 85 70 2 1
3 1300 2 2 95 5 100 85 70 2 1
4 1646 2 5 93 3 NA NA NA 4 NA
5 799 3 5 93 1 85 60 90 4 1
6 1328 4 NA 92 5 50 50 50 2 1
educ sexo ingresos marital voto96 quien96 su_ecopas clintpst gorepst gbushpst
1 1 2 NA 1 5 NA NA NA NA NA
2 1 2 36297 2 NA NA NA 50 50 50
3 1 2 3856 2 1 1 1 NA NA NA
4 3 2 NA 2 1 3 2 NA NA NA
5 1 1 83308 2 1 5 2 30 40 100
6 1 1 32926 1 1 3 1 20 50 65
relig voto00 confipol difclint
1 7 NA NA NA
2 1 5 NA -35
3 1 NA NA NA
4 1 1 NA NA
5 1 1 1 -55
6 1 1 2 -30
summary(df_usa) # Resumen estadistico id region consipol edad
Min. : 1.0 Min. :1.000 Min. :1.000 Min. :18.00
1st Qu.: 453.5 1st Qu.:2.000 1st Qu.:3.000 1st Qu.:34.00
Median : 905.0 Median :3.000 Median :5.000 Median :45.00
Mean : 905.7 Mean :2.614 Mean :4.339 Mean :47.21
3rd Qu.:1358.5 3rd Qu.:3.000 3rd Qu.:5.000 3rd Qu.:58.00
Max. :1811.0 Max. :4.000 Max. :7.000 Max. :97.00
NA's :184 NA's :9
intecamp clintpre gorepre gbushpre
Min. :1.000 Min. : 0.00 Min. : 0.00 Min. : 0.00
1st Qu.:1.000 1st Qu.: 30.00 1st Qu.: 40.00 1st Qu.: 40.00
Median :3.000 Median : 60.00 Median : 60.00 Median : 60.00
Mean :2.857 Mean : 55.48 Mean : 57.57 Mean : 56.14
3rd Qu.:3.000 3rd Qu.: 80.00 3rd Qu.: 75.00 3rd Qu.: 70.00
Max. :5.000 Max. :100.00 Max. :100.00 Max. :100.00
NA's :13 NA's :33 NA's :46
aborto anonac educ sexo
Min. :1.000 Min. :1.000 Min. :1.000 Min. :1.000
1st Qu.:2.000 1st Qu.:1.000 1st Qu.:2.000 1st Qu.:1.000
Median :3.000 Median :2.000 Median :3.000 Median :2.000
Mean :2.885 Mean :1.863 Mean :2.512 Mean :1.563
3rd Qu.:4.000 3rd Qu.:3.000 3rd Qu.:3.000 3rd Qu.:2.000
Max. :4.000 Max. :3.000 Max. :3.000 Max. :2.000
NA's :49 NA's :30 NA's :7
ingresos marital voto96 quien96 su_ecopas
Min. : 518 Min. :1.000 Min. :1.000 Min. :1.00 Min. :1.000
1st Qu.:23632 1st Qu.:1.000 1st Qu.:1.000 1st Qu.:1.00 1st Qu.:1.000
Median :50735 Median :1.000 Median :1.000 Median :1.00 Median :2.000
Mean :49709 Mean :2.364 Mean :2.182 Mean :2.13 Mean :1.804
3rd Qu.:75744 3rd Qu.:4.000 3rd Qu.:5.000 3rd Qu.:3.00 3rd Qu.:2.000
Max. :99918 Max. :6.000 Max. :5.000 Max. :5.00 Max. :3.000
NA's :45 NA's :14 NA's :13 NA's :596 NA's :884
clintpst gorepst gbushpst relig
Min. : 0.00 Min. : 0.00 Min. : 0.00 Min. :1.000
1st Qu.: 30.00 1st Qu.: 40.00 1st Qu.: 40.00 1st Qu.:1.000
Median : 60.00 Median : 60.00 Median : 60.00 Median :2.000
Mean : 53.73 Mean : 54.47 Mean : 56.14 Mean :2.784
3rd Qu.: 80.00 3rd Qu.: 75.00 3rd Qu.: 80.00 3rd Qu.:3.000
Max. :100.00 Max. :100.00 Max. :100.00 Max. :7.000
NA's :266 NA's :271 NA's :269 NA's :274
voto00 confipol difclint
Min. :1.000 Min. :1.000 Min. :-100.0000
1st Qu.:1.000 1st Qu.:1.000 1st Qu.: -10.0000
Median :1.000 Median :2.000 Median : 0.0000
Mean :1.958 Mean :2.385 Mean : -0.8091
3rd Qu.:1.000 3rd Qu.:3.000 3rd Qu.: 10.0000
Max. :5.000 Max. :4.000 Max. : 97.0000
NA's :253 NA's :353 NA's :272
table(df_usa$consipol)
1 2 3 4 5 6 7
82 158 351 109 528 250 145
usa <- read.spss("usa.sav",
use.value.labels = T,
to.data.frame=TRUE)
str(usa)#Ver estructura de bases de datos, tipo de variablePAQUETE DPLYR
El paquete dplyr es el más útil en R para la manipulación de datos, una de las ventajas es que se pueda usar el pipe para combinar diferentes funciones en R. Para no tener que escribirlo, se genera mediante control shift M. En pocas palabras, reemplaza la “,” para concatenar(unir) varios comandos.
FILTER: filtrar filas según un criterio
Filtra casos o filas que cumplen con el criterio. Por ejemplo, aca estamos filtrando de la data usa.sav las personas que son judíos
usa %>%
filter(relig=="Catolico", intecamp=="1. Mucho")
usa %>%
filter(edad >= 50)
usa %>%
filter(intecamp=="1. Mucho", sexo=="Hombre", consipol=="1. Muy liberal")
usa %>%
filter(intecamp=="1. Mucho", sexo=="Mujer", consipol=="7. Muy Conservador")SELECT: Seleccionando subconjunto de variables
Selecciona columnas o mejor dicho, variables de su conjunto de datos, según nombre.
En este comando estamos especificando que queremos seleccionar de la data usa, las variables interés en las campañas (intecamp) y sexo.
inte= usa %>%
select(intecamp, sexo)
inteSi queremos quitar variable ponemos el signo de menos. Salen todas las varibales menos las del si voto en las elecciones del 96 (voto96) y por quién.
Lo podríamos volver un objeto para poder trabajar con ello
# quitando variables
usa %>%
select(-voto96, -quien96)
menos96 <- usa %>%
select(-voto96, -quien96)
menos96 SUMMARISE: Crear resumenes de datos
Resume cualquiera de las funciones anteriores, para aplicarla a un grupo de datos.
En este caso, queremos sacar el promedio de aprobación de Al Gore luego de su gestión. Para eso usamos sumarise. Mencionamos los datos de la base usa, luego la variable que se creará en base a ella, que será la media de la variable gorepst, omitiendo los valores perdidos
Solo con variables numéricas (ojo)
#Promedio aprobación Al Gore post elecciones
usa %>%
summarise(promgorepost = mean(gorepst, na.rm = T))
#CORROBORAMOS
class(usa$gorepst) Acá nos menciona un error, dice que el argumento no es numérico. Las convertimos
#CORREGIMOS
usa$gorepst<- as.numeric(usa$gorepst)
usa$gorepre<- as.numeric(usa$gorepre)
usa %>%
summarise(MediaAprobGorePost = mean(gorepst, na.rm = T))COUNT: contar casos en base a una variable
Nos ayuda a contar las observaciones.
Vamos a contar los casos de las personas de acuerdo al nivel educativo.
Se puede observar que la mayoría tiene un nivel educativo mayor al de secundaria.
usa %>%
count(relig)
usa %>%
count(educ,sort = FALSE) #numero de personas en base a nivel educativo, con SORT=T estamos diciendo que nos ordene los datos de manera descendenteMUTATE Y ARRANGE
Crea nuevas columnas conservando las variables existentes. En esta ocasión estamos creando una nueva variable que vendría a ser la diferencia de la aprobación de Al Gore antes y luego de su gestión.
Esta función es un poco más larga, pero no es difícil. Primero crearemos una nueva variable que será la diferencia de la aprobación de Al Gore antes y luego de su gestión, y luego de eso, queremos que esa variable creada, se ordene de manera descendente. Finalmente, queremos que los resultados muestre únicamente las variables de ID, difgore, gorepre y gorepst para ver la diferencia.
usagoredesc<- usa %>%
mutate(difgore = gorepst - gorepre) %>% arrange(., desc(gorepst)) %>%
select(id, difgore, gorepre, gorepst)Vamos a poner gorepost como función en arrange para ver su aprobación más alta.
#diferencia más alta
usa %>%
mutate(difgore = gorepst - gorepre) %>%
arrange(desc(difgore)) %>%
select(id, difgore, gorepre, gorepst)TRANSMUTE
También existe la función transmute, que realiza lo mismo solo que muestra únicamente la nueva variable creada (no se agrega a la base de datos)
Crearemos la vida variable de disfrencia pero con la aprobación George Bush
Vamos a cambiarla a numérica, para evitar que ocurra el mismo error.
usa$gbushpst<- as.numeric(usa$gbushpst)
usa$gbushpre<- as.numeric(usa$gbushpre)
usabush <- usa %>%
transmute(difbush = gbushpst - gbushpre) %>%
arrange(desc(difbush))group_by: Agrupar datos
Agrupa diferentes observaciones de manera que el conjunto de datos original no cambie.
Aca estamos indicando que se agrupe la data en base a posición política.
Finalmente, agruparemos datos y usaremos más de una función
En el primer ejemplo, lo que haremos es agrupar los datos mediante la posición política, y usaremos sumarise para sacar el promedio de la aprobación de Bush post gestión Vemos los resultados. Vemos una tendencia que los más conservadores tenían una aprobación más alta de Bush
usa.g <- usa %>%
group_by(consipol) %>%
summarise(mean = mean(gbushpst,na.rm=TRUE), n = n())
usa.gAhora con Al Gore ¿los datos se voltean? Los encuestados que se consideran muy Liberales, aprueban más la gestión de Al Gore, a diferencia de los muy conservadores.
usa.b <- usa %>%
group_by(consipol) %>%
summarise(mean = mean(gorepst,na.rm=TRUE), n = n())
usa.bReferencias:
Mendoza, B. (2018). R para principiantes. Libro electrónico. En https://bookdown.org/jboscomendoza/r-principiantes4/
Hanck, C., Arnold, M., Gerber, A., & Schmelzer, M. (2019). Introduction to Econometrics with R. University of Duisburg-Essen, 1-9. En https://www.econometrics-with-r.org/
Mackenzie, Charles E. 1980. Coded character sets: history and development. Reading, Mass: Addison-Wesley Pub. Co. En https://archive.org/details/mackenzie-coded-char-sets
Santiago Sotelo & María Pía van Oordt (2023). Qlab.
Tiscornia Pablo - Introducción al procesamiento de datos con R para Ciencias Sociales. Aplicación práctica en la Encuesta Permanente de Hogares (EPH-INDEC). En https://intro-r-eph.netlify.app/bio.html)
Weksler, K. & Shokida. Curso de R para procesamiento de datos de la Encuesta Permanente de Hogares. En https://diegokoz.github.io/Curso_R_EPH_clases/
Wickham, H., & Grolemund, G. (2016). R for data science: import, tidy, transform, visualize, and model data. ” O’Reilly Media, Inc.” En First Edition y Second Edition
Más recursos:
Data Política: Manual R para estadística aplicada al análisis político. Data Política: Lima.
POL278 - Estadística para el análisis político 1. Jefes de práctica: Alexander Benites, Reyna Osorio, Gabriel Ramos y Almendra Rodriguez.
Plantilla de los principales comandos del curso ESTADISTICA PARA EL ANALISIS POLITICO 1
Por qué las estadísticas inteligentes son la clave para combatir el crimen
El contenido de este curso se ofrece bajo una licencia Dominio público. El contenido de este curso puede considerarse bajo esta licencia a menos que se notifique de manera diferente.